package com.admin.common.util;

import com.admin.common.thread.ThreadPoolManager;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.springframework.util.FileCopyUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class FileZipUtil {

	/**
	 * 仅支持网络文件
	 * @param fileUrlList 压缩的文件路径(整个完整路径)
	 * @param zipFileStorePath 压缩后的文件存储路径
	 * @throws Exception
	 */
	public static Boolean fileDownZip(List<String> fileUrlList, String zipFileStorePath) throws Exception {
		//创建临时存储文件夹
		File directory = new File(System.getProperty("user.dir") + File.separator + "temp");
		if (!directory.exists()) {
			directory.mkdirs();
		}

		//下载网络图片到本地临时文件夹
		downLoadFile(fileUrlList, directory);

		//压缩文件
		zip(zipFileStorePath, directory);

		//删除临时文件
		deleteTempFile(directory);

		return true;
	}

	/**
	 * 仅支持本地文件
	 * @param fileUrlList 压缩的文件路径(整个完整路径)
	 * @param zipFileStorePath 压缩后的文件存储路径
	 * @throws Exception
	 */
	public static Boolean fileCopyZip(List<String> fileUrlList, String zipFileStorePath) throws Exception {
		//创建临时存储文件夹
		File directory = new File(System.getProperty("user.dir") + File.separator + "temp");
		if (!directory.exists()) {
			directory.mkdirs();
		}

		//复制图片到本地临时文件夹
		fileCopy(fileUrlList, directory);

		//压缩文件
		zip(zipFileStorePath, directory);

		//删除临时文件
		deleteTempFile(directory);

		return true;
	}

	private static void fileCopy(List<String> fileUrlList, File directory) throws Exception {
		for (String fileUrl : fileUrlList) {
			List<Future<Boolean>> futureTaskList = new ArrayList<>();
			Future<Boolean> task = ThreadPoolManager.get().submit(() -> {
				try {
					File destFile = new File(directory, fileUrl.substring(fileUrl.lastIndexOf("/")));
					FileCopyUtils.copy(new File(fileUrl), destFile);
					return true;
				} catch (Exception e) {
					throw new RuntimeException(e);
				}

			});

			futureTaskList.add(task);
			for (Future<Boolean> t : futureTaskList) {
				t.get();
			}

		}
	}


	private static void downLoadFile(List<String> fileUrlList, File directory) throws Exception {
		for (String fileUrl : fileUrlList) {
			List<Future<Boolean>> futureTaskList = new ArrayList<>();
			Future<Boolean> task = ThreadPoolManager.get().submit(() -> {
				FileOutputStream outStream = null;
				try {
					//定义一个URL对象，就是你想下载的图片的URL地址
					URL url = new URL(fileUrl);
					//打开连接
					HttpURLConnection conn = (HttpURLConnection) url.openConnection();
					//设置请求方式为"GET"
					conn.setRequestMethod("GET");
					//超时响应时间为60秒
					conn.setConnectTimeout(60 * 1000);
					//通过输入流获取图片数据
					InputStream is = conn.getInputStream();
					//得到图片的二进制数据，以二进制封装得到数据，具有通用性
					byte[] data = readInputStream(is);
					//创建一个文件对象用来保存图片
					File imageFile = new File(directory, fileUrl.substring(fileUrl.lastIndexOf("/")));
					//创建输出流

					outStream = new FileOutputStream(imageFile);
					//写入数据
					outStream.write(data);

					return true;
				} catch (Exception e) {
					throw new RuntimeException(e);
				} finally {
					if (outStream != null) {
						try {
							outStream.close();
						} catch (IOException e) {
							throw new RuntimeException(e);
						}
					}
				}

			});

			futureTaskList.add(task);
			for (Future<Boolean> t : futureTaskList) {
				t.get();
			}

		}


	}

	private static void deleteTempFile(File directory) {
		if (directory.isDirectory()) {
			for (File file : directory.listFiles()) {
				System.out.println(file.delete());
			}
		}
		directory.delete();
	}

	public static byte[] readInputStream(InputStream inStream) throws Exception {
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		//创建一个Buffer字符串
		byte[] buffer = new byte[6024];
		//每次读取的字符串长度，如果为-1，代表全部读取完毕
		int len;
		//使用一个输入流从buffer里把数据读取出来
		while ((len = inStream.read(buffer)) != -1) {
			//用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
			outStream.write(buffer, 0, len);
		}
		//关闭输入流
		inStream.close();
		//把outStream里的数据写入内存
		return outStream.toByteArray();
	}

	private static void zip(String zipFileName, File inputFile) throws Exception {
		ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
		zip(out, inputFile, "");
		out.flush();
		out.close();
	}

	private static void zip(ZipOutputStream out, File f, String base) throws Exception {
		if (f.isDirectory()) {
			File[] fl = f.listFiles();
			out.putNextEntry(new ZipEntry(base + "/"));
			base = base.length() == 0 ? "" : base + "/";
			for (int i = 0; i < fl.length; i++) {
				zip(out, fl[i], base + fl[i].getName());
			}
		} else {
			out.putNextEntry(new ZipEntry(base));
			FileInputStream in = new FileInputStream(f);
			int b;
			while ((b = in.read()) != -1) {
				out.write(b);
			}
			in.close();
		}
	}
	
	 public static void main(String [] temp){       
		 try {
			 List<String> urlList = new ArrayList<>();
			 urlList.add("https://bluesky-68324107-1178.oss-cn-shanghai.aliyuncs.com/uploads/files/52f609cc-0c65-4218-b7ff-b43669a8de7a.jpg");
			 fileDownZip(urlList, "C:\\\\Users\\\\hzboom\\\\Desktop\\\\test.zip");
		 }catch (Exception ex) {
				 ex.printStackTrace();    
			 }   
		}
}